#include "../../muduo_source/server.hpp"
// void HandleClose(Channel* channel)
// {
//     DEBUG_LOG("close: %d\n",channel->Fd());
//     //std::cout << "close : " << channel->Fd() << std::endl;
//     channel->Remove();
//     delete channel;
// }

// void HandleRead(Channel* channel)
// {
//     int fd = channel->Fd();
//     char buf[1024] = {0};
//     int ret = recv(fd,buf,1023,0);//0:默认阻塞
//     if(ret <= 0)
//     {
//         //先解除监控，再关闭
//         HandleClose(channel);
//     }
//     channel->EnableWrite(); //启动写事件监控 
//     DEBUG_LOG("%s\n",buf);
// }

// void HandleWrite(Channel* channel)
// {
//     int fd = channel->Fd();
//     const char* str = "今天是下雨天";
//     int ret = send(fd,str,strlen(str),0);
//     if(ret < 0)
//     {
//         //先解除监控，再关闭
//         printf("发送失败了\n");
//         HandleClose(channel);
//     }
//     channel->DisableWrite(); // 关闭写事件监控
// }

// void HandleError(Channel* channel)
// {
//     HandleClose(channel);
// }

// void HandleEvents(EventLoop* loop,Channel* channel,time_t timerid)
// {
//     loop->TimerRefresh(timerid);
// }

// void Acceptor(EventLoop* loop, Channel* lst_channel)
// {
//     int fd = lst_channel->Fd(); //客户的fd
//     int newfd = accept(fd,nullptr,nullptr);
//     if(newfd < 0)
//     {
//         return ;
//     }
//     time_t timerid = rand() % 10000;
//     //连接获取成功，为该连接创建Channel并添加监控
//     Channel *channel = new Channel(loop,newfd);
//     channel->SetReadCallback(std::bind(HandleRead,channel));   // 可读事件回调
//     channel->SetWriteCallback(std::bind(HandleWrite,channel));  // 可写事件回调
//     channel->SetErrorCallback(std::bind(HandleError,channel));  // 错误事件回调
//     channel->SetCloseCallback(std::bind(HandleClose,channel));  // 关闭事件回调
//     channel->SetEventsCallback(std::bind(HandleEvents,loop,channel,timerid)); //任意事件回调

//     //定时销毁任务必须在读事件启动之前，因为有可能读事件监控启动后，立即有了事件，这时候还没有任务 
//     //想要的需求是：触发任意事件时，都要刷新活跃度，保证在通信期间不能因为延时事件到了而关闭事件
//     loop->TimerAdd(timerid,10,std::bind(HandleClose,channel));//非活跃链接的超时释放操作：10s后关闭连接
//     //先将销毁任务压入任务队列，再启动读事件监控。
//     //因为如果先启动读事件监控的话，可能立即有了事件，但是此时还没设置销毁任务，该事件在通信完成后，就不会被销毁，后面的任务池就得不到执行。
//     //开启读事件监控
//     channel->EnableRead();
// }



// //管理所有的连接
// std::unordered_map<uint64_t,PtrConnection> _conns;

// void OnMessage(const PtrConnection& conn,Buffer* buff)
// {

//     //打印收到的消息
//     DEBUG_LOG("我收到了消息：%s",buff->GetReadPos());
    
//     buff->MoveReadOffset(buff->GetReadableSpace());//读指针此时移动到与写指针相同位置
//     std::string str = "服务器收到数据啦，hello";
//     //将回复写入到发送缓冲区
//     conn->Send(str.c_str(),str.size());
// }

// void OnConnected(const PtrConnection& conn)
// {
//     DEBUG_LOG("NEW CONNECTION: %p",conn.get());
// }

// void ConnectionDestroy(const PtrConnection& conn)
// {
//     DEBUG_LOG("客户端关闭了连接\n");
//     _conns.erase(conn->Id());
// }


// uint64_t conn_id = 0;
// void Acceptor(EventLoop* loop, Channel* lst_channel)
// {
//     int fd = lst_channel->Fd(); //客户的fd
//     int newfd = accept(fd,nullptr,nullptr);
//     if(newfd < 0)
//     {
//         return ;
//     }
//     conn_id++;
//     //连接获取成功，为该连接创建Channel并添加监控
//     PtrConnection conn(new Connection(loop,conn_id,newfd));
//     //这些参数不用再传了，因为在设置回调的时候已经传过了(shared_from_this和_in_buffer)
//     conn->SetMessageCallback(std::bind(&OnMessage,std::placeholders::_1,std::placeholders::_2));   //业务处理回调
//     conn->SetConnectedCallback(std::bind(&OnConnected,std::placeholders::_1));  //连接就绪完成回调
//     conn->SetClosedCallback(std::bind(&ConnectionDestroy,std::placeholders::_1));  //连接关闭回调

//     //启动非活跃超时销毁
//     conn->EnableInactiveRelease(10);
//     //链接成功后是CONNECTING待初始化状态，现在要对该连接进行初始化
//     conn->Established();

//     //放入哈希表中进行管理
//     _conns.insert(make_pair(conn_id,conn));    
    
// }

// int main()
// {
//     srand(time(NULL));
//     EventLoop loop;
//     Socket lis_sock;
//     lis_sock.CreateServer(8085);
//     //为套接字设置一个Channel帮它进行事件的管理
//     Channel lis_channel(&loop,lis_sock.FD());   //Channel被Poller总经理管理，它自己帮助Socket管理事件。
//     lis_channel.SetReadCallback(std::bind(&Acceptor,&loop,&lis_channel)); //管理的具体方法：回调时，获取新链接，并为新链接创建Channel并添加监控
    
//     //非常重要
//     lis_channel.EnableRead(); // 启动可读事件监控
    
//     //开始监控事件并进行处理
//     while(1)
//     {
//         //开始监控
//         loop.Start();
//         // //客户端连接后，获取新链接
//         // int newfd = lis_sock.Accept();
//         // if(newfd < 0)   continue;

//         // //创建一个回应"客户端"，相当于例子中的服务员，给客户端提供一对一服务
//         // Socket cli_sock(newfd);
//         // char buf[1024]; 
//         // int ret = cli_sock.Recv(buf,sizeof(buf));
//         // if(ret < 0)
//         // {
//         //     cli_sock.Close();
//         //     continue;
//         // }
//         // DEBUG_LOG("%d get a mesg : %s",newfd,buf);
        
//         // cli_sock.Send(buf,sizeof(buf));
//         // DEBUG_LOG("%d Send a mesg : %s",newfd,buf);
//         // cli_sock.Close();
//     }
//     lis_sock.Close();
//     return 0;
// }

//管理所有的连接
std::unordered_map<uint64_t,PtrConnection> _conns;
void OnMessage(const PtrConnection& conn,Buffer* buff)
{
    //打印收到的消息
    DEBUG_LOG("我收到了消息：%s",buff->GetReadPos());
    
    buff->MoveReadOffset(buff->GetReadableSpace());//读指针此时移动到与写指针相同位置
    std::string str = "服务器收到数据啦，hello";
    //将回复写入到发送缓冲区
    conn->Send(str.c_str(),str.size());
}

void OnConnected(const PtrConnection& conn)
{
    DEBUG_LOG("NEW CONNECTION: %p",conn.get());
}

void ConnectionDestroy(const PtrConnection& conn)
{
    DEBUG_LOG("关闭连接\n"); //不一定是客户端主动退出，而是客户端非活跃
    _conns.erase(conn->Id());
}

EventLoop base_loop; //进行监听
uint64_t conn_id = 0;
std::vector<LoopThread> threads(2); // 使用threads暂时创建2个LoopThread对象
int next_loop = 0;

//这个fd不是我们自己传的，而是在Acceptor类中的HandlerRead中获取新链接拿到的newfd
void NewConnection(int fd)
{
    conn_id++;
    next_loop = (next_loop + 1) % 2;
    //从属线程threads[next_loop].GetLoop()，才真正对事件进行处理
    PtrConnection conn(new Connection(threads[next_loop].GetLoop(),conn_id,fd));
    //这些参数不用再传了，因为在设置回调的时候已经传过了(shared_from_this和_in_buffer)
    conn->SetMessageCallback(std::bind(&OnMessage,std::placeholders::_1,std::placeholders::_2));   //业务处理回调
    conn->SetConnectedCallback(std::bind(&OnConnected,std::placeholders::_1));  //连接就绪完成回调
    conn->SetClosedCallback(std::bind(&ConnectionDestroy,std::placeholders::_1));  //连接关闭回调
    //启动非活跃超时销毁
    conn->EnableInactiveRelease(10);
    //链接成功后是CONNECTING待初始化状态，现在要对该连接进行初始化
    conn->Established();

    //放入哈希表中进行管理
    _conns.insert(make_pair(conn_id,conn));    
}

int main()
{
    srand(time(NULL));
    Acceptor acceptor(&base_loop,8085);
    acceptor.SetAcceptCallback(std::bind(&NewConnection,std::placeholders::_1));  //这只是表示一个占位符
    acceptor.Listen(); //启动可读事件监控
    
    //主线程开始监控事件,只负责监听新链接
    base_loop.Start();

    return 0;
}